package org.jeecg.modules.third.qiyuesuo.service;

import com.qiyuesuo.sdk.v2.SdkClient;
import com.qiyuesuo.sdk.v2.bean.Action;
import com.qiyuesuo.sdk.v2.bean.Category;
import com.qiyuesuo.sdk.v2.bean.Contract;
import com.qiyuesuo.sdk.v2.bean.Document;
import com.qiyuesuo.sdk.v2.bean.Signatory;
import com.qiyuesuo.sdk.v2.bean.TemplateParam;
import com.qiyuesuo.sdk.v2.bean.User;
import com.qiyuesuo.sdk.v2.bean.UserAuthInfo;
import com.qiyuesuo.sdk.v2.json.JSONUtils;
import com.qiyuesuo.sdk.v2.param.SignParam;
import com.qiyuesuo.sdk.v2.request.ContractDetailRequest;
import com.qiyuesuo.sdk.v2.request.ContractDraftRequest;
import com.qiyuesuo.sdk.v2.request.ContractPageRequest;
import com.qiyuesuo.sdk.v2.request.ContractSignCompanyRequest;
import com.qiyuesuo.sdk.v2.request.ContractSignLpRequest;
import com.qiyuesuo.sdk.v2.request.DocumentDownloadRequest;
import com.qiyuesuo.sdk.v2.request.UserAuthPageRequest;
import com.qiyuesuo.sdk.v2.response.ContractPageResult;
import com.qiyuesuo.sdk.v2.response.SdkResponse;
import com.qiyuesuo.sdk.v2.response.UserAuthPageResult;
import com.qiyuesuo.sdk.v2.utils.IOUtils;
import org.apache.http.entity.ContentType;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.third.qiyuesuo.constant.QiYueSuoConstant;
import org.jeecg.modules.third.qiyuesuo.utils.PdfToImageUtil;
import org.jeecg.modules.system.controller.CommonController;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


/**
 * @Description: 电子签章服务
 * @author: luruirui
 * @date: 2021年04月14日 9:57
 */
@Service
public class QiYueSuoService {
    private final Logger logger = LoggerFactory.getLogger(QiYueSuoService.class);

    private SdkClient sdkClient = null;

    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    QiYueSuoService(){
        sdkClient = new SdkClient(QiYueSuoConstant.URL_TEST, QiYueSuoConstant.APP_TOKEN, QiYueSuoConstant.APP_SECRET);
    }
    /**
     * 签署公章
     *
     * @param contractId
     * @return
     */
    public SdkResponse companySealSignByCategoryConfig(Long contractId){
        // 签署公章
        SignParam param = new SignParam();
        param.setContractId(contractId);
        ContractSignCompanyRequest request = new ContractSignCompanyRequest(param);
        String response = sdkClient.service(request);
        SdkResponse<Object> responseObj = JSONUtils.toQysResponse(response);
        if(responseObj.getCode() == 0) {
//            logger.info("公章签署成功");
        } else {
            logger.info("公章签署失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
        }
        return responseObj;
    }

    /**
     * 签署法人章
     *
     * @param contractId
     * @return
     */
    public SdkResponse companyLpSignByCategoryConfig(Long contractId){
        // 签署法人章
        SignParam param = new SignParam();
        param.setContractId(contractId);
        ContractSignLpRequest request = new ContractSignLpRequest(param);
        String response = sdkClient.service(request);
        SdkResponse<Object> responseObj = JSONUtils.toQysResponse(response);
        if(responseObj.getCode() == 0) {
//            logger.info("法人章签署成功");
        } else {
            logger.info("法人章签署失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
        }
        return responseObj;
    }

    /**
     * 合同详情
     */
    public Contract contractDetail(Long contractId){
        // 合同详情
        ContractDetailRequest request = new ContractDetailRequest(contractId);
        String response = sdkClient.service(request);
        SdkResponse<Contract> responseObj = JSONUtils.toQysResponse(response, Contract.class);
        Contract contract = responseObj.getResult();
        if(responseObj.getCode() == 0) {
//            logger.info("合同详情查询，合同主题：{}", contract.getSubject());
        } else {
            logger.info("请求失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
        }
        return contract;
    }
    /**
     * 合同是否签署完成
     */
    public boolean izContractCompleted(Contract contract){
        if(contract == null){
            throw new JeecgBootException("未获取到合同");
        }
        String status = contract.getStatus();
//        合同状态：DRAFT（草稿） RECALLED（已撤回），SIGNING（签署中），REJECTED（已退回），COMPLETE（已完成），
//        EXPIRED（已过期），FILLING（拟定中），INVALIDING（作废中），INVALIDED（已作废），FORCE_END（强制结束）
        return status.equals("COMPLETE") ? true : false;
    }
    /**
    * 获取个人认证链接
    */
    public SdkResponse<UserAuthPageResult> verifyDriverInfo(HyDriver driver){
        UserAuthPageRequest request = new UserAuthPageRequest();
        request.setMode("IVS");
        request.setUser(new User(driver.getDriverName(), driver.getTelephone(), "MOBILE"));
        List<String> otherModes = new ArrayList<>();
        otherModes.add("FACE");
        //otherModes.add("MANUAL");
        request.setOtherModes(otherModes);
        String response = sdkClient.service(request);
        SdkResponse < UserAuthPageResult > responseObj = JSONUtils.toQysResponse(response, UserAuthPageResult.class);
//        logger.info(responseObj.getResult().getAuthUrl());
        return responseObj;
    }
    /**
     * 下载合同文档
     */
    public void downloadContract(Contract contract){
        if(contract == null){
            throw new JeecgBootException("未获取到合同");
        }
        List<Document> documents = contract.getDocuments();
        Long documentId = documents.get(0).getId();
        // 下载合同文档
        DocumentDownloadRequest request = new DocumentDownloadRequest(documentId);
        FileOutputStream fos = null;
        try {
            //documents/20210417/123456789.pdf
            String address = uploadpath + File.separator + "documents" + File.separator + DateUtils.getDate("yyyyMMdd");
            //String address = "c://opt//upFiles" + File.separator + "documents";
            String path = address + File.separator + contract.getId() + ".pdf";
            File fileDir = new File(address);
            if(!fileDir.exists()) {
                fileDir.mkdirs();//创建目录
            }
            //下载合同
            fos = new FileOutputStream(path);
            sdkClient.download(request, fos);
            IOUtils.safeClose(fos);
//            logger.info("下载合同文档成功, 地址：{}", path);
        }catch (IOException e){
            logger.info(e.toString());
            throw new RuntimeException("下载合同文件写入失败，请重试");
        }
    }
    /**
     * 获取车辆挂靠声明图片
     */
    public List<String> getContractImgSrc(Contract contract){
        downloadContract(contract);
        //String fileAddr = "c://opt//upFiles" + File.separator + "documents" + File.separator;
        String sysPath = uploadpath;
        String fileAddr = "documents" + File.separator + DateUtils.getDate("yyyyMMdd") + File.separator;
        String filename = Long.toString(contract.getId());
        List<String> srcList = PdfToImageUtil.pdf2Jpg(sysPath + File.separator + fileAddr, filename);
        for (int i = 0; i < srcList.size(); i++) {
            srcList.set(i, fileAddr + srcList.get(i));
        }
        return srcList;
    }

    /**
     * 签署页面 生成用户的签署链接
     *
     * @param contractId
     * @param signUser
     * @return
     * @throws Exception
     */
    public SdkResponse<ContractPageResult> signPage(Long contractId, User signUser){
//        String cbkPage = "http://localhost:8080/wlhy168/api/wlhy/qiyuesuo/signVechicleCompleteCbk";
        String cbkPage = "";
        // 合同页面
        ContractPageRequest request = new ContractPageRequest(contractId, signUser, cbkPage);
        String response = sdkClient.service(request);
        SdkResponse<ContractPageResult> responseObj = JSONUtils.toQysResponse(response, ContractPageResult.class);
        if(responseObj.getCode() == 0) {
//            ContractPageResult result = responseObj.getResult();
//            logger.info("signPage合同页面地址为:{}", result.getPageUrl());
        } else {
            logger.info("signPage签署页面获取失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
        }
        return responseObj;
    }

    /**
     * 根据业务分类配置创建合同草稿并发起合同
     * 车辆挂靠声明
     * @param driver
     * @return
     */
    public SdkResponse<Contract> draftVechileHang(HyDriver driver){
        // 合同基本参数
        Contract contract = new Contract();
        contract.setCategory(new Category(QiYueSuoConstant.TEST_CTR_VECHILE_ID));// 设置业务分类ID,套用该业务分类的配置
        contract.setSend(true);
        // 个人签署方
        Signatory signatory1 = new Signatory();
        signatory1.setTenantName(driver.getDriverName());//签署方名称
        signatory1.setTenantType("PERSONAL");//签署方类型
        signatory1.setReceiver(new User(driver.getDriverName(), driver.getTelephone(), "MOBILE"));
        signatory1.setSerialNo(1);
        UserAuthInfo userAuthInfo = new UserAuthInfo();
        userAuthInfo.setIdCardNo(driver.getIdcard());
        signatory1.setUserAuthInfo(userAuthInfo);
        // 设置签署方
        contract.addSignatory(signatory1);
        //contract.addSignatory(signatory2);
        contract.addTemplateParam(new TemplateParam("司机姓名", driver.getDriverName()));
        contract.addTemplateParam(new TemplateParam("司机身份证号", driver.getIdcard()));
        // 创建合同
        ContractDraftRequest request = new ContractDraftRequest(contract);
        String response = sdkClient.service(request);
        SdkResponse<Contract> responseObj = JSONUtils.toQysResponse(response, Contract.class);
        // 返回结果
        if(responseObj.getCode() == 0) {
//            Contract result = responseObj.getResult();
//            logger.info("draft创建合同成功，合同ID:{}", result.getId());
        } else {
            logger.info("draft请求失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
        }
        return responseObj;
    }
    //司机签署车辆挂靠协议
    public Result<?> signVehicleHang(HyDriver driver){
        //合同发起
        SdkResponse<Contract> draft = draftVechileHang(driver);
        // 返回结果
        if(draft.getCode() == 0) {
//            logger.info("创建合同草稿成功，并发起，合同ID：{}", draft.getResult().getId());
        }else{
            String message = "创建合同草稿失败，错误码:" + draft.getCode() +"，错误信息:" + draft.getMessage();
            logger.info(message);
            return Result.error(message);
        }

        //获取个人认证信息链接
        SdkResponse<UserAuthPageResult> verifyResponse = verifyDriverInfo(driver);
        // 返回结果
        if(verifyResponse.getCode() == 0) {
//            logger.info("获取个人认证信息链接成功，认证ID：{}", verifyResponse.getResult().getAuthId());
        }else{
            String message = "获取个人认证信息链接失败，错误码:" + verifyResponse.getCode() +"，错误信息:" + verifyResponse.getMessage();
            logger.info(message);
            return Result.error(message);
        }
        //获取页面链接
        User driverUser = new User(driver.getDriverName(), driver.getTelephone(), "MOBILE");
        SdkResponse<ContractPageResult> pageResponse = signPage(draft.getResult().getId(), driverUser);
        if(pageResponse.getCode() == 0) {
            ContractPageResult result = pageResponse.getResult();
            String url = result.getPageUrl();
            Long contractId = draft.getResult().getId();
//            logger.info("合同页面地址为:{}", result.getPageUrl());
            HashMap data = new HashMap();
            data.put("url", url);
            data.put("contractId", Long.toString(contractId));
            return Result.OK(data);
        } else {
            String message = "合同页面获取失败，错误码:" + pageResponse.getCode() +"，错误信息:" + pageResponse.getMessage();
            logger.info(message);
            return Result.error(message);
        }
    }
    //检测车辆挂靠声明并转图片
    public Result<?> checkVehicleHang(String affiliationAgreement){
        //检测司机车辆挂靠声明是否签署完成
        Long contractId = Long.parseLong(affiliationAgreement);
        Contract contract = contractDetail(contractId);
        if(contract == null){
            return Result.error("未获取到合同");
        }
        boolean izContractCompleted = izContractCompleted(contract);
        if(izContractCompleted){
            //下载pdf>转jpg
            List<String> imgSrcList = getContractImgSrc(contract);
            String src = imgSrcList.size() > 0 ? imgSrcList.get(0) : "";
//            logger.info("挂靠声明图片地址:{} ", src);
            if(src.equals("")){
                return Result.error("合同PDF转图片失败，请重试");
            }else{
                //返回图片
                return Result.OK(src);
            }
        }else{
            return Result.error(contract.getSubject() + "尚未签署完成，请签署！");
        }
    }

    /**
     * 根据业务分类配置创建合同草稿并发起合同
     * 账期支付合同
     * TODO 未完成代码
     * @return
     */
    public SdkResponse<Contract> draftPayment(){
        // 合同基本参数
        Contract contract = new Contract();
        contract.setCategory(new Category(QiYueSuoConstant.TEST_CTR_PAYMENT_ID));// 设置业务分类ID,套用该业务分类的配置
        contract.setSend(true);
        // 公司签署方
        Signatory signatory1 = new Signatory();
        signatory1.setTenantName("168");//签署方名称
        signatory1.setTenantType("COMPANY");//签署方类型
        signatory1.setReceiver(new User("路明", "18003190541", "MOBILE"));
        Action action1 = new Action("COMPANY", 1);
        signatory1.addAction(action1);
        signatory1.setSerialNo(1);
        // 对接方
        Signatory signatory2 = new Signatory();
        signatory2.setTenantName("天津中鑫恒国际贸易有限公司");
        signatory2.setTenantType("COMPANY");
        signatory2.setReceiver(new User("路蕊蕊", "18340812976", "MOBILE"));
        signatory2.setSerialNo(2);
        Action action2 = new Action("COMPANY", 1);
        signatory2.addAction(action2);
        // 设置签署方
        contract.addSignatory(signatory1);
        contract.addSignatory(signatory2);
        // 若业务分类中包含参数模板，设置参数内容
        contract.addTemplateParam(new TemplateParam("甲方名称", "天津中鑫恒国际贸易有限公司"));
        contract.addTemplateParam(new TemplateParam("甲方信用代码", "123456XT"));
        // 创建合同
        ContractDraftRequest request = new ContractDraftRequest(contract);
        String response = sdkClient.service(request);
        SdkResponse<Contract> responseObj = JSONUtils.toQysResponse(response, Contract.class);
        // 返回结果
        if(responseObj.getCode() == 0) {
//            Contract result = responseObj.getResult();
//            logger.info("draftPayment创建合同成功，合同ID:{}", result.getId());
        } else {
            logger.info("draftPayment请求失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
        }
        return responseObj;
    }
    //货主签署账期支付合同
    public SdkResponse<ContractPageResult> signPayment(){
        if(sdkClient == null){
            //TODO 错误处理
            logger.info("契约锁客户端SdkClient生成为null");
            return null;
        }
        /**
         * 根据业务分类配置进行合同发起
         */
        SdkResponse<Contract> draft = draftPayment();
        companySealSignByCategoryConfig(draft.getResult().getId());
        /**
         * 平台方签署完成，签署方签署可采用
         * （1）接收短信的方式登录契约锁云平台进行签署
         * （2）生成内嵌页面签署链接进行签署（下方生成的链接）
         * （3）JS-SDK签署（仅支持个人）
         */
        User signUser = new User("路蕊蕊", "18340812976", "MOBILE");
        SdkResponse<ContractPageResult> pageResponse = signPage(draft.getResult().getId(), signUser);
        //url = pageResponse.getResult().getPageUrl();

        return pageResponse;
    }


    public static void main(String[] args) throws Exception{
        HyDriver driver = new HyDriver();
        driver.setDriverName("孟祥");
        driver.setTelephone("18233016761");
        driver.setIdcard("130403199103303313");
        QiYueSuoService qiYueSuoService = new QiYueSuoService();
        //qiYueSuoService.signVehicleHang(driver);
        //检测司机车辆挂靠声明是否签署完成
        String contractId = "2820491727880589774";
        Result result = qiYueSuoService.checkVehicleHang(contractId);
        String pathString = File.separator + result.getResult().toString();
        System.out.println("图片地址：" + pathString);
        //上传
        CommonController controller = new CommonController();

        File file = new File(pathString);
        InputStream inputStream = new FileInputStream(file);
        MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getName(),
                ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
//        controller.uploadLocal(multipartFile, "temp");
    }
}
